package hu.imind.phonecalc.server;

import java.util.Map;

import javax.jdo.PersistenceManager;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import hu.imind.phonecalc.client.LoginService;
import hu.imind.phonecalc.client.dto.LoginInfo;
import hu.imind.phonecalc.entity.PhoneCalcUser;

import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import com.google.gdata.client.http.AuthSubUtil;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class LoginServiceImpl extends RemoteServiceServlet implements
LoginService {
    /**
     * The auth token is stored in cookie. If it is not set, then
     * we are not authenticated.
     */
    public LoginInfo login(String requestUri) {
        UserService userService = UserServiceFactory.getUserService();
        User user = userService.getCurrentUser();
        LoginInfo loginInfo = new LoginInfo();

        if (user != null) {
            loginInfo.setLoggedIn(true);
            loginInfo.setEmailAddress(user.getEmail());
            loginInfo.setNickname(user.getNickname());
            loginInfo.setLogoutUrl(userService.createLogoutURL(requestUri));
            // check if we have a valid google contacts token
            checkToken(requestUri, loginInfo);

            // query the stored numbers
            PersistenceManager pm = PMF.get().getPersistenceManager();
            PhoneCalcUser u = null;
            try{
                u = pm.getObjectById(PhoneCalcUser.class, loginInfo.getEmailAddress());
            }catch (Exception e) {
                System.err.println("could not get data from the db");
            }
            if (u != null) {
                loginInfo.setWorkNumbers(u.getWorkNumbers().getValue());
                loginInfo.setPrivNumbers(u.getPrivNumbers().getValue());
                loginInfo.setBillsBigTable(u.getBills());
            }
            
            // store the email address in session
            HttpSession session = getThreadLocalRequest().getSession();
            session.setAttribute("email", user.getEmail());
        } else {
            loginInfo.setLoggedIn(false);
            loginInfo.setLoginUrl(userService.createLoginURL(requestUri));
        }
        return loginInfo;
    }

    public LoginInfo loginAuthSub(String requestUri) {
        LoginInfo loginInfo = new LoginInfo();
        checkToken(requestUri, loginInfo);
        return loginInfo;
    }

    private void checkToken(String requestUri, LoginInfo loginInfo) {
        HttpServletRequest request = getThreadLocalRequest();
        String token = getTokenCookie(request);
        if (token == null || token.length() == 0) {
            // we don't have a token, return the login url
            getAuthSubLoginUrl(requestUri, loginInfo);
        } else if (token.length() > 0) {
            Map<String, String> tokenInfo;
            try {
                tokenInfo = AuthSubUtil.getTokenInfo(token, null);
                if (tokenInfo != null) {
                    loginInfo.setToken(token);
                    loginInfo.setContactAuthorized(true);
                }
            } catch (Exception e) {
                //e.printStackTrace();
            }
        }
        if (loginInfo.isContactAuthorized() != true) {
            loginInfo.setContactAuthorized(false);
        }
    }

    public static String getTokenCookie(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies == null) {
            return null;
        }
        for (int i = 0; i < cookies.length; i++) {
            if (cookies[i].getName().equalsIgnoreCase("googleAuthToken")) {
                return cookies[i].getValue();
            }
        }
        return null;
    }


    private void getAuthSubLoginUrl(String requestUri, LoginInfo loginInfo) {
        // TODO: check if we are on https
        HttpServletRequest request = getThreadLocalRequest();
        String next = "http://" + request.getServerName();
        if (request.getServerPort() != 80) {
            next += ":" + request.getServerPort();
        }
        next += "/imind_phonecalc/logincallback";
        String scope = "https://www.google.com/m8/feeds/contacts/default/full"; // contacts feed
        boolean secure = false;
        boolean session = true;
        loginInfo.setAuthSubLoginUrl(AuthSubUtil.getRequestUrl(next, scope, secure, session));
    }


}
